import base64
import json
import logging
import time
import threading
from concurrent.futures import ThreadPoolExecutor
# 保留requests库用于同步版本
import requests
import cv2

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)



def send_json_post(url: str, data: dict, headers: dict = None, timeout: int = 10) -> dict:
    """
    发送JSON格式的POST请求 (同步版本)
    
    参数:
        url: 请求的URL地址
        data: 要发送的JSON数据（字典格式）
        headers: 可选的请求头
    
    返回:
        响应结果（字典格式）
    
    异常:
        requests.exceptions.RequestException: 当请求失败时抛出
    """
    # 如果没有提供headers，则使用默认的JSON请求头
    if headers is None:
        headers = {
            'Content-Type': 'application/json',
        }
    
    try:
        # 记录请求开始时间
        start_time = time.time()
        
        # 发送POST请求
        response = requests.post(
            url=url,
            data=data,
            headers=headers
        )
        
        # 计算请求耗时
        elapsed_time = time.time() - start_time
        logger.info(f"请求完成，耗时: {elapsed_time:.2f}秒，状态码: {response.status_code}")
        
        # 检查响应状态码
        response.raise_for_status()
        
        # 尝试解析响应为JSON
        try:
            result = response.json()
            logger.info(f"响应解析成功: {result}")
            return result
        except json.JSONDecodeError as json_err:
            logger.warning(f"响应解析失败: {json_err}")
            return {'status_code': response.status_code, 'text': response.text}
    
    except requests.exceptions.ConnectionError as conn_err:
        # 处理连接异常
        logger.error(f"连接失败: {conn_err}")
        logger.error(f"无法连接到 {url}，请检查网络连接和服务器状态")
        raise
    
    except requests.exceptions.Timeout as timeout_err:
        # 处理超时异常
        logger.error(f"请求超时: {timeout_err}")
        raise
    
    except requests.exceptions.RequestException as e:
        # 处理其他请求异常
        logger.error(f"请求失败: {e}")
        raise


def thread_send_json_post(url: str, data: dict, headers: dict = None, timeout: int = 10) -> dict:
    """
    发送JSON格式的POST请求 (多线程版本)
    
    参数:
        url: 请求的URL地址
        data: 要发送的JSON数据（字典格式）
        headers: 可选的请求头
    
    返回:
        响应结果（字典格式）
    
    异常:
        requests.exceptions.RequestException: 当请求失败时抛出
    """
    # 实际上，多线程版本可以直接复用同步版本的实现
    # 因为线程池会处理并发执行
    return send_json_post(url, data, headers, timeout)


class ThreadPoolManager:
    """
    线程池管理器，用于管理HTTP请求的并发执行
    """
    def __init__(self, max_workers: int = 20):
        """
        初始化线程池管理器
        
        参数:
            max_workers: 线程池中的最大工作线程数
        """
        self.executor = ThreadPoolExecutor(max_workers=max_workers)
        self.futures = {}
        self.lock = threading.Lock()
        self.counter = 0

    def submit_task(self, url: str, data: dict, headers: dict = None, timeout: int = 10) -> int:
        """
        提交一个HTTP请求任务到线程池
        
        参数:
            url: 请求的URL地址
            data: 要发送的JSON数据（字典格式）
            headers: 可选的请求头
            timeout: 超时时间
        
        返回:
            任务ID，用于后续获取结果
        """
        with self.lock:
            task_id = self.counter
            self.counter += 1
            future = self.executor.submit(thread_send_json_post, url, data, headers, timeout)
            self.futures[task_id] = future
        return task_id

    def get_result(self, task_id: int, timeout: int = None) -> dict:
        """
        获取指定任务的结果
        
        参数:
            task_id: 任务ID
            timeout: 等待结果的超时时间
        
        返回:
            任务结果（字典格式）
        
        异常:
            KeyError: 当任务ID不存在时抛出
            concurrent.futures.TimeoutError: 当等待超时时抛出
            Exception: 当任务执行过程中发生异常时抛出
        """
        if task_id not in self.futures:
            raise KeyError(f"任务ID {task_id} 不存在")
        
        future = self.futures[task_id]
        try:
            result = future.result(timeout=timeout)
            # 任务完成后从futures中移除
            with self.lock:
                del self.futures[task_id]
            return result
        except Exception as e:
            # 发生异常时也从futures中移除
            with self.lock:
                if task_id in self.futures:
                    del self.futures[task_id]
            raise

    def shutdown(self, wait: bool = True):
        """
        关闭线程池
        
        参数:
            wait: 是否等待所有任务完成
        """
        self.executor.shutdown(wait=wait)

# 创建全局线程池管理器实例
thread_pool = ThreadPoolManager(max_workers=5)


def _process_and_send_img(img_data, img_url):
    """
    处理并发送图片数据的辅助函数
    
    参数:
        img_data: 图片数据（numpy数组）
        img_url: 发送图片的URL地址
    
    返回:
        响应结果
    """
    try:
        # 将图像编码为JPEG格式
        _, img_encoded = cv2.imencode(".jpg", img_data)
        # 获取编码后的字节数据
        img_bytes = img_encoded.tobytes()
        
        # 直接发送请求
        result = send_json_post(img_url, img_bytes)
        print(f"图片数据已异步发送，响应结果: {result}")
        return result
    except Exception as e:
        print(f"处理和发送图片数据失败: {e}")
        raise

def thread_send_img(img_data):
    """
    发送图片数据 (多线程异步版本)
    
    参数:
        img_data: 图片数据（numpy数组）
    
    说明:
        该函数总是以异步方式发送数据，不等待返回结果，包括图像编码也在异步线程中执行
    """
    img_url = "http://20.9.12.15:20194/engine-monitor/carVideo/sendPicture"
    
    try:
        # 提交处理函数到线程池执行器
        thread_pool.executor.submit(_process_and_send_img, img_data, img_url)
        print(f"图片数据处理任务已异步提交")
        return None
    except Exception as e:
        print(f"提交图片数据处理任务失败: {e}")
        raise

def send_num(left, right):
    """
    发送数字数据 (同步版本)
    
    参数:
        left: 左侧数字
        right: 右侧数字
    """
    # 测试URL (可以替换为实际的API端点)
    test_url = "http://192.168.1.112:8181/gps/sendTestData"
    
    # 测试数据
    test_data:dict = {}
    test_data["left"]= left
    test_data["right"]= right
    
    
    try:
        data = json.dumps(test_data)
        # 发送请求
        result = send_json_post(test_url, data)
        
        # 打印结果
        print(f"请求成功! 响应结果: {result}")
    except Exception as e:
        print(f"请求失败: {e}")


def thread_send_num(left, right):
    """
    发送数字数据 (多线程异步版本)
    
    参数:
        left: 左侧数字
        right: 右侧数字
    
    说明:
        该函数总是以异步方式发送数据，不等待返回结果
    """
    # 测试URL (可以替换为实际的API端点)
    test_url = "http://20.9.12.15:20194/engine-monitor/carVideo/sendTrafficFlow"
    
    # 测试数据
    test_data:dict = {}
    test_data["left"]= left
    test_data["right"]= right
    
    
    try:
        data = json.dumps(test_data)
        # 提交任务到线程池
        task_id = thread_pool.submit_task(test_url, data)
        print(f"数字数据请求已提交到线程池，任务ID: {task_id}")
        return None
    except Exception as e:
        print(f"提交数字数据请求失败: {e}")
        raise


if __name__ == "__main__":
    # 示例：异步发送图片数据，不等待返回结果
    try:
        img_path = r"/Users/stary/Pictures/temp/1.jpg"
        # 使用OpenCV读取图片
        img_data = cv2.imread(img_path)
        if img_data is None:
            raise FileNotFoundError(f"无法读取图片: {img_path}")
        print(f"成功读取图片: {img_path}")
        
        # 异步发送，不等待结果
        thread_send_img(img_data)
        print("图片数据已异步发送，不等待返回结果")
        
        time.sleep(5)
        # 关闭线程池
        thread_pool.shutdown()
        print("线程池已关闭")
    except Exception as e:
        print(f"程序执行出错: {e}")

